home *** CD-ROM | disk | FTP | other *** search
/ STraTOS 1997 April & May / STraTOS 1 - 1997 April & May.iso / CD01 / INTERNET / SITES / GRAHAM / XA_6S.ZIP / SOURCE / STD_WIDG.C < prev    next >
Encoding:
C/C++ Source or Header  |  1996-10-11  |  23.3 KB  |  740 lines

  1. /*
  2.  * XaAES - XaAES Ain't the AES
  3.  *
  4.  * A multitasking AES replacement for MiNT
  5.  *
  6.  */
  7.  
  8. #include <OSBIND.H>
  9. #include <VDI.H>
  10. #include <memory.h>
  11. #include <string.h>
  12. #include "XA_TYPES.H"
  13. #include "XA_DEFS.H"
  14. #include "XA_GLOBL.H"
  15. #include "KERNAL.H"
  16. #include "K_DEFS.H"
  17. #include "KERNAL.H"
  18. #include "GRAF_MOU.H"
  19. #include "C_WINDOW.H"
  20. #include "RECTLIST.H"
  21. #include "ALL_WIDG.H"
  22. #include "SCRLWIDG.H"
  23. #include "CLOSWIDG.H"
  24. #include "RESZWIDG.H"
  25. #include "TITLWIDG.H"
  26. #include "FULLWIDG.H"
  27. #include "INFOWIDG.H"
  28. #include "OBJCWIDG.H"
  29. #include "ICONWIDG.H"
  30. #include "FORM_DO.H"
  31. #include "OBJECTS.H"
  32. #include "SYSTEM.H"
  33.  
  34. OBJECT *def_widgets;
  35.  
  36. /*
  37.     WINDOW WIDGET SET HANDLING ROUTINES
  38.     This module handles the behaviour of the window widgets.
  39. */
  40.  
  41. MFDB widget_bm;
  42.  
  43. /* Convert widget bitmaps (16*16*4bit device independant format) to device specific format */
  44. /* for the current screen device. */
  45. /* Asides from looking pretty, this should make the default widget set work with any */
  46. /* colour screen mode and any graphics card (right up to 24 bits/pixel). */
  47. void fix_bitmaps(void)
  48. {
  49.     def_widgets[WIDG_SIZE].ob_x=def_widgets[WIDG_SIZE].ob_y=0;
  50.     def_widgets[WIDG_LOGO].ob_x=def_widgets[WIDG_LOGO].ob_y=0;
  51.     def_widgets[WIDG_CLOSER].ob_x=def_widgets[WIDG_CLOSER].ob_y=0;
  52.     def_widgets[WIDG_UP].ob_x=def_widgets[WIDG_UP].ob_y=0;
  53.     def_widgets[WIDG_DOWN].ob_x=def_widgets[WIDG_DOWN].ob_y=0;
  54.     def_widgets[WIDG_LEFT].ob_x=def_widgets[WIDG_LEFT].ob_y=0;
  55.     def_widgets[WIDG_RIGHT].ob_x=def_widgets[WIDG_RIGHT].ob_y=0;
  56.     def_widgets[WIDG_ICONIFY].ob_x=def_widgets[WIDG_ICONIFY].ob_y=0;
  57.     def_widgets[WIDG_FULL].ob_x=def_widgets[WIDG_FULL].ob_y=0;
  58.  
  59. #if 0
  60.     MFDB dest;
  61.  
  62.     widget_bm.fd_w=ICON_W;
  63.     widget_bm.fd_h=ICON_H;
  64.     widget_bm.fd_wdwidth=1;
  65. #if MONO_WIDGETS
  66.     widget_bm.fd_nplanes=1;
  67. #else
  68.     widget_bm.fd_nplanes=4;
  69. #endif
  70.     widget_bm.fd_stand=1;
  71.     dest=widget_bm;
  72.     dest.fd_stand=0;
  73.  
  74. /* Transform the XaAES logo */
  75.     widget_bm.fd_addr=(void*)bitmap_xaaes16_s;
  76.     dest.fd_addr=(void*)bitmap_xaaes16_s;
  77.     vr_trnfm(V_handle,&widget_bm,&dest);
  78.     widget_bm.fd_addr=(void*)bitmap_xaaes16;
  79.     dest.fd_addr=(void*)bitmap_xaaes16;
  80.     vr_trnfm(V_handle,&widget_bm,&dest);
  81.     
  82. /* Transform the actual window widgets */
  83.     widget_bm.fd_addr=(void*)widget_bitmap_close;
  84.     dest.fd_addr=(void*)widget_bitmap_close;
  85.     vr_trnfm(V_handle,&widget_bm,&dest);
  86.     widget_bm.fd_addr=(void*)widget_bitmap_close_s;
  87.     dest.fd_addr=(void*)widget_bitmap_close_s;
  88.     vr_trnfm(V_handle,&widget_bm,&dest);
  89.     widget_bm.fd_addr=(void*)widget_bitmap_size;
  90.     dest.fd_addr=(void*)widget_bitmap_size;
  91.     vr_trnfm(V_handle,&widget_bm,&dest);
  92.     widget_bm.fd_addr=(void*)widget_bitmap_size_s;
  93.     dest.fd_addr=(void*)widget_bitmap_size_s;
  94.     vr_trnfm(V_handle,&widget_bm,&dest);
  95.     widget_bm.fd_addr=(void*)widget_bitmap_full;
  96.     dest.fd_addr=(void*)widget_bitmap_full;
  97.     vr_trnfm(V_handle,&widget_bm,&dest);
  98.     widget_bm.fd_addr=(void*)widget_bitmap_full_s;
  99.     dest.fd_addr=(void*)widget_bitmap_full_s;
  100.     vr_trnfm(V_handle,&widget_bm,&dest);
  101.  
  102.     widget_bm.fd_addr=(void*)widget_bitmap_left;
  103.     dest.fd_addr=(void*)widget_bitmap_left;
  104.     vr_trnfm(V_handle,&widget_bm,&dest);
  105.     widget_bm.fd_addr=(void*)widget_bitmap_left_s;
  106.     dest.fd_addr=(void*)widget_bitmap_left_s;
  107.     vr_trnfm(V_handle,&widget_bm,&dest);
  108.  
  109.     widget_bm.fd_addr=(void*)widget_bitmap_right;
  110.     dest.fd_addr=(void*)widget_bitmap_right;
  111.     vr_trnfm(V_handle,&widget_bm,&dest);
  112.     widget_bm.fd_addr=(void*)widget_bitmap_right_s;
  113.     dest.fd_addr=(void*)widget_bitmap_right_s;
  114.     vr_trnfm(V_handle,&widget_bm,&dest);
  115.  
  116.     widget_bm.fd_addr=(void*)widget_bitmap_up;
  117.     dest.fd_addr=(void*)widget_bitmap_up;
  118.     vr_trnfm(V_handle,&widget_bm,&dest);
  119.     widget_bm.fd_addr=(void*)widget_bitmap_up_s;
  120.     dest.fd_addr=(void*)widget_bitmap_up_s;
  121.     vr_trnfm(V_handle,&widget_bm,&dest);
  122.     
  123.     widget_bm.fd_addr=(void*)widget_bitmap_down;
  124.     dest.fd_addr=(void*)widget_bitmap_down;
  125.     vr_trnfm(V_handle,&widget_bm,&dest);
  126.     widget_bm.fd_addr=(void*)widget_bitmap_down_s;
  127.     dest.fd_addr=(void*)widget_bitmap_down_s;
  128.     vr_trnfm(V_handle,&widget_bm,&dest);
  129.  
  130.     widget_bm.fd_addr=(void*)widget_bitmap_iconify;
  131.     dest.fd_addr=(void*)widget_bitmap_iconify;
  132.     vr_trnfm(V_handle,&widget_bm,&dest);
  133.     widget_bm.fd_addr=(void*)widget_bitmap_iconify_s;
  134.     dest.fd_addr=(void*)widget_bitmap_iconify_s;
  135.     vr_trnfm(V_handle,&widget_bm,&dest);
  136.  
  137.     widget_bm=dest;
  138. #endif
  139. }
  140.  
  141. /* Set the active/pending widget behaviour for a client */
  142. void set_widget_active(XA_WINDOW *wind, XA_WIDGET *widg, WidgetCallback wc)
  143. {
  144.     XA_PENDING_WIDGET *pw;
  145.     short clnt_pid=wind->owner;
  146.         
  147.     pw=(XA_PENDING_WIDGET*)malloc(sizeof(XA_PENDING_WIDGET));
  148.     if (!pw)
  149.         return;
  150.  
  151.     if (clients[clnt_pid].widget_active)
  152.         free(clients[clnt_pid].widget_active);
  153.  
  154.     pw->wind=wind;
  155.     pw->widg=widg;
  156.     pw->action=wc;
  157.     clients[clnt_pid].widget_active=pw;
  158. }
  159.  
  160. /* Cancel the active/pending widget for a client */
  161. void cancel_widget_active(XA_WINDOW *wind)
  162. {
  163.     XA_PENDING_WIDGET *pw;
  164.     short clnt_pid=wind->owner;
  165.     
  166.     pw=clients[clnt_pid].widget_active;
  167.     clients[clnt_pid].widget_active=NULL;
  168.     if (pw) free(pw);
  169. }
  170.  
  171. /* Convert window relative widget coords to absolute screen coords */
  172. void rp_2_ap(XA_WINDOW *wind, XA_WIDGET *widg, short *x, short *y)
  173. {
  174.     XA_WIDGET_LOCATION rp=widg->loc;
  175.     XA_RELATIVE rt;
  176.  
  177.     rt=rp.relative_type;
  178.  
  179.     *x=wind->x;
  180.     *y=wind->y;
  181.     
  182.     switch(rt)
  183.     {
  184.         case LT:
  185.             *x+=rp.x;
  186.             *y+=rp.y;
  187.             break;
  188.         case LB:
  189.             *x+=rp.x;
  190.             *y+= (wind->h - widg->h - rp.y);
  191.             break;
  192.         case RT:
  193.             *x+= (wind->w - widg->w - rp.x);
  194.             *y+=rp.y;
  195.             break;
  196.         case RB:
  197.             *x+= (wind->w - widg->w - rp.x);
  198.             *y+= (wind->h - widg->h - rp.y);
  199.             break;
  200.         case CT:
  201.             *x+= (wind->w/2 - widg->w/2);
  202.             *y+=rp.y;
  203.             break;
  204.         case CB:
  205.             *x+= (wind->w/2 - widg->w/2);
  206.             *y+= (wind->h - widg->h - rp.y);
  207.             break;
  208.     }
  209. }
  210.  
  211. /*
  212.     New display widget code - standard widget set is now in the system.rsc file
  213. */
  214. void display_widget_bitmap(short x, short y, short index)
  215. {
  216.     display_object(def_widgets,index,x,y);
  217. }
  218.  
  219. /* Calculate the size of the work area for a window and store it */
  220. /* - this is needed because the locations of widgets are relative and */
  221. /*   can be modified. */
  222. /* Actually, this updates all the dynamic sized elements from the standard widget set... */
  223. /* (namely: work area, sliders and title bar) */
  224. void calc_work_area(XA_WINDOW *wind)
  225. {
  226.     XA_WIDGET *widg;
  227.     XA_RELATIVE rt;
  228.     WidgetCallback disp;
  229.     short x0, y0;
  230.     short x1, y1;
  231.     short tx0,tx1;
  232.     short slx0,slx1,sly0,sly1;
  233.     short wx,wy;
  234.     short f;
  235.  
  236.     x0=wind->x+4; y0=wind->y+4;
  237.     x1=wind->x+wind->w-8; y1=wind->y+wind->h-8;
  238.     
  239.     slx0=x0; slx1=x1-ICON_W-1;
  240.     sly0=y0; sly1=y1-ICON_H-1;
  241.     tx0=wind->x+3; tx1=wind->x+wind->w-6;
  242.     
  243.     for (f=0; f<XA_MAX_WIDGETS; f++)
  244.     {
  245.         widg=wind->widgets+f;
  246.         disp=widg->behaviour[XACB_DISPLAY];        /* get the redraw function for this widget */
  247.         if (disp)    /* If the widget is displayed, include it in the calculation */
  248.         {
  249.             rp_2_ap(wind, widg, &wx, &wy);
  250.             rt=widg->loc.relative_type;
  251.             switch(rt)
  252.             {
  253.                 case LT:
  254.                     if (wy+widg->h+2>y0)
  255.                         y0=wy+widg->h+2;
  256.                     if (((f!=XAW_TITLE)&&(wx+widg->w+3>tx0))
  257.                         &&(widg->loc.y<=wind->widgets[XAW_TITLE].loc.y+wind->widgets[XAW_TITLE].h))
  258.                     {
  259.                         tx0=wx+widg->w+3;
  260.                     }
  261.                     break;
  262.                 case LB:
  263.                     if (wy<y1+2)
  264.                         y1=wy-2;
  265.                     if ((f!=XAW_HSLIDE)&&(wx+widg->w+2>slx0))
  266.                         slx0=wx+widg->w+1;
  267.                     break;
  268.                 case RT:
  269.                     if ((f!=XAW_VSLIDE)&&(wy+widg->h+2>sly0))
  270.                         sly0=wy+widg->h+1;
  271.                     if ((wx<x1+2)&&(wy+widg->h+2>y0))
  272.                     {
  273.                         x1=wx-2;
  274.                         y0=wy+widg->h+2;
  275.                     }
  276.                     if (wx-3<tx1)
  277.                         tx1=wx-3;
  278.                     break;
  279.                 case RB:
  280.                     if ((wx<x1+2)&&(wy<y1+2))
  281.                     {
  282.                         x1=wx-2;
  283.                         y1=wy-2;
  284.                     }
  285.                     if ((f!=XAW_HSLIDE)&&(wx<slx1+1))
  286.                         slx1=wx-1;
  287.                     if ((f!=XAW_VSLIDE)&&(wy<sly1+1))
  288.                         sly1=wy-1;
  289.                     break;
  290.                 case CT:
  291.                     if (wy+widg->h+2>y0)
  292.                         y0=wy+widg->h+2;
  293.                     break;
  294.                 case CB:
  295.                     if (wy<y1+2)
  296.                         y1=wy-2;
  297.                     break;
  298.             }
  299.         }
  300.     }
  301.     wind->wx=x0;                            /* Update work area */
  302.     wind->wy=y0;
  303.     wind->ww=x1-x0;
  304.     wind->wh=y1-y0;
  305.     wind->widgets[XAW_TITLE].w=tx1-tx0;        /* Update title bar length */
  306.     wind->widgets[XAW_TITLE].loc.x=tx0-wind->x;
  307.     if (wind->active_widgets&HSLIDE)        /* Update horizontal slider */
  308.     {
  309.         wind->widgets[XAW_HSLIDE].w=slx1-slx0;
  310.     }
  311.     if (wind->active_widgets&VSLIDE)        /* Update vertical slider */
  312.     {
  313.         wind->widgets[XAW_VSLIDE].h=sly1-sly0;
  314.     }
  315. }
  316.  
  317. /* Define the widget locations using window relative coordinates. */
  318. const XA_WIDGET_LOCATION stdl_close={LT,1,1};
  319. const XA_WIDGET_LOCATION stdl_full={RT,3,1};
  320. const XA_WIDGET_LOCATION stdl_iconify={RT,3,1};
  321. const XA_WIDGET_LOCATION stdl_title={LT,21,1};
  322. const XA_WIDGET_LOCATION stdl_resize={RB,3,3};
  323. const XA_WIDGET_LOCATION stdl_rscroll={RB,ICON_W+3,3};
  324. const XA_WIDGET_LOCATION stdl_lscroll={LB,1,3};
  325. const XA_WIDGET_LOCATION stdl_uscroll={RT,3,1};
  326. const XA_WIDGET_LOCATION stdl_dscroll={RB,3,ICON_H+3};
  327. const XA_WIDGET_LOCATION stdl_vslide={RT,3,ICON_H+2};
  328. const XA_WIDGET_LOCATION stdl_hslide={LB,ICON_W+1,3};
  329. const XA_WIDGET_LOCATION stdl_info={LT,1,1};
  330. const XA_WIDGET_LOCATION stdl_menu={LT,1,WIDGET_SIZE+5};
  331.  
  332. /* Setup the required 'standard' widgets for a window. These are the ordinary GEM */
  333. /* behaviours. These can be changed for any given window if you want special behaviours. */
  334. void standard_widgets(XA_WINDOW *wind, long tp)
  335. {
  336.     short wd,bh,top_w=wind->w;
  337.     long bit_mask;
  338.     
  339.     wind->active_widgets=tp;                /* Fill in the active widgets summary */
  340.     wind->widgets_on_top=0;
  341.     
  342.     DIAGS(("standard widgets=%ld\n",tp));
  343.     
  344.     for (wd=0; wd<XA_MAX_WIDGETS; wd++)        /* Initially tag all behaviours as NULL so we can tell */
  345.     {                                        /* which ones we have actually attatched. */
  346.         for(bh=0; bh<COUNT_XACB; bh++)
  347.         {
  348.             wind->widgets[wd].behaviour[bh]=NULL;
  349.         }
  350.         wind->widgets[wd].stuff=NULL;
  351.     }
  352.  
  353.     if (tp&CLOSE)
  354.     {
  355.         wind->widgets[XAW_CLOSE].behaviour[XACB_DISPLAY]=&display_close_widget;
  356.         wind->widgets[XAW_CLOSE].behaviour[XACB_CLICK]=&click_close;
  357.         wind->widgets[XAW_CLOSE].behaviour[XACB_DCLICK]=NULL;
  358.         wind->widgets[XAW_CLOSE].behaviour[XACB_DRAG]=NULL;
  359.         wind->widgets[XAW_CLOSE].loc=stdl_close;
  360.         wind->widgets[XAW_CLOSE].stat=XAW_PLAIN;
  361.         wind->widgets[XAW_CLOSE].w=ICON_W;
  362.         wind->widgets[XAW_CLOSE].h=ICON_H;
  363.         top_w-=WIDGET_SIZE;
  364.         wind->widgets_on_top++;
  365.     }
  366.  
  367.     if (tp&FULLER)
  368.     {
  369.         wind->widgets[XAW_FULL].behaviour[XACB_DISPLAY]=&display_full;
  370.         wind->widgets[XAW_FULL].behaviour[XACB_CLICK]=&click_full;
  371.         wind->widgets[XAW_FULL].behaviour[XACB_DCLICK]=NULL;
  372.         wind->widgets[XAW_FULL].behaviour[XACB_DRAG]=NULL;
  373.         wind->widgets[XAW_FULL].loc=stdl_full;
  374.         wind->widgets[XAW_FULL].stat=XAW_PLAIN;
  375.         wind->widgets[XAW_FULL].w=ICON_W;
  376.         wind->widgets[XAW_FULL].h=ICON_H;
  377.         top_w-=WIDGET_SIZE;
  378.         wind->widgets_on_top++;
  379.     }
  380.  
  381.     if (tp&SMALLER)
  382.     {
  383.         DIAGS(("SETTING ICONIFY WIDGET\n"));
  384.         wind->widgets[XAW_ICONIFY].behaviour[XACB_DISPLAY]=&display_iconify;
  385.         wind->widgets[XAW_ICONIFY].behaviour[XACB_CLICK]=&click_iconify;
  386.         wind->widgets[XAW_ICONIFY].behaviour[XACB_DCLICK]=NULL;
  387.         wind->widgets[XAW_ICONIFY].behaviour[XACB_DRAG]=NULL;
  388.         wind->widgets[XAW_ICONIFY].loc=stdl_iconify;
  389.         if (tp&FULLER)
  390.         {
  391.             wind->widgets[XAW_ICONIFY].loc.x+=wind->widgets[XAW_FULL].w;
  392.             DIAGS(("shifting for fuller\n"));
  393.         }
  394.         wind->widgets[XAW_ICONIFY].stat=XAW_PLAIN;
  395.         wind->widgets[XAW_ICONIFY].w=ICON_W;
  396.         wind->widgets[XAW_ICONIFY].h=ICON_H;
  397.         top_w-=WIDGET_SIZE;
  398.         wind->widgets_on_top++;
  399.     }
  400.  
  401.     if (tp&SIZER)
  402.     {
  403.         wind->widgets[XAW_RESIZE].behaviour[XACB_DISPLAY]=&display_resize;
  404.         wind->widgets[XAW_RESIZE].behaviour[XACB_CLICK]=NULL;
  405.         wind->widgets[XAW_RESIZE].behaviour[XACB_DCLICK]=NULL;
  406.         wind->widgets[XAW_RESIZE].behaviour[XACB_DRAG]=&drag_resize;
  407.         wind->widgets[XAW_RESIZE].loc=stdl_resize;
  408.         wind->widgets[XAW_RESIZE].stat=XAW_PLAIN;
  409.         wind->widgets[XAW_RESIZE].w=ICON_W;
  410.         wind->widgets[XAW_RESIZE].h=ICON_H;
  411.     }
  412.     
  413.     if (tp&UPARROW)
  414.     {
  415.         wind->widgets[XAW_UP].behaviour[XACB_DISPLAY]=&display_uscroll;
  416.         wind->widgets[XAW_UP].behaviour[XACB_CLICK]=&click_uscroll;
  417.         wind->widgets[XAW_UP].behaviour[XACB_DCLICK]=NULL;
  418.         wind->widgets[XAW_UP].behaviour[XACB_DRAG]=&click_uscroll;
  419.         wind->widgets[XAW_UP].loc=stdl_uscroll;
  420.         wind->widgets[XAW_UP].stat=XAW_PLAIN;
  421.         wind->widgets[XAW_UP].w=ICON_W;
  422.         wind->widgets[XAW_UP].h=ICON_H;
  423.     }
  424.     if (tp&DNARROW)
  425.     {
  426.         wind->widgets[XAW_DOWN].behaviour[XACB_DISPLAY]=&display_dscroll;
  427.         wind->widgets[XAW_DOWN].behaviour[XACB_CLICK]=&click_dscroll;
  428.         wind->widgets[XAW_DOWN].behaviour[XACB_DCLICK]=NULL;
  429.         wind->widgets[XAW_DOWN].behaviour[XACB_DRAG]=&click_dscroll;
  430.         wind->widgets[XAW_DOWN].loc=stdl_dscroll;
  431.         wind->widgets[XAW_DOWN].stat=XAW_PLAIN;
  432.         wind->widgets[XAW_DOWN].w=ICON_W;
  433.         wind->widgets[XAW_DOWN].h=ICON_H;
  434.     }
  435.     if (tp&LFARROW)
  436.     {
  437.         wind->widgets[XAW_LEFT].behaviour[XACB_DISPLAY]=&display_lscroll;
  438.         wind->widgets[XAW_LEFT].behaviour[XACB_CLICK]=&click_lscroll;
  439.         wind->widgets[XAW_LEFT].behaviour[XACB_DCLICK]=NULL;
  440.         wind->widgets[XAW_LEFT].behaviour[XACB_DRAG]=&click_lscroll;
  441.         wind->widgets[XAW_LEFT].loc=stdl_lscroll;
  442.         wind->widgets[XAW_LEFT].stat=XAW_PLAIN;
  443.         wind->widgets[XAW_LEFT].w=ICON_W;
  444.         wind->widgets[XAW_LEFT].h=ICON_H;
  445.     }
  446.     if (tp&RTARROW)
  447.     {
  448.         wind->widgets[XAW_RIGHT].behaviour[XACB_DISPLAY]=&display_rscroll;
  449.         wind->widgets[XAW_RIGHT].behaviour[XACB_CLICK]=&click_rscroll;
  450.         wind->widgets[XAW_RIGHT].behaviour[XACB_DCLICK]=NULL;
  451.         wind->widgets[XAW_RIGHT].behaviour[XACB_DRAG]=&click_rscroll;
  452.         wind->widgets[XAW_RIGHT].loc=stdl_rscroll;
  453.         wind->widgets[XAW_RIGHT].stat=XAW_PLAIN;
  454.         wind->widgets[XAW_RIGHT].w=ICON_W;
  455.         wind->widgets[XAW_RIGHT].h=ICON_H;
  456.     }
  457.  
  458.     if (tp&VSLIDE)
  459.     {
  460.         wind->widgets[XAW_VSLIDE].behaviour[XACB_DISPLAY]=&display_vslide;
  461.         wind->widgets[XAW_VSLIDE].behaviour[XACB_CLICK]=&drag_vslide;
  462.         wind->widgets[XAW_VSLIDE].behaviour[XACB_DCLICK]=NULL;
  463.         wind->widgets[XAW_VSLIDE].behaviour[XACB_DRAG]=&drag_vslide;
  464.         wind->widgets[XAW_VSLIDE].loc=stdl_vslide;
  465.         wind->widgets[XAW_VSLIDE].stat=XAW_PLAIN;
  466.         wind->widgets[XAW_VSLIDE].w=ICON_W;
  467.         wind->widgets[XAW_VSLIDE].h=ICON_H;
  468.         wind->widgets[XAW_VSLIDE].stuff=(void*)malloc(sizeof(XA_SLIDER_WIDGET));
  469.         ((XA_SLIDER_WIDGET*)wind->widgets[XAW_VSLIDE].stuff)->position=0;
  470.         ((XA_SLIDER_WIDGET*)wind->widgets[XAW_VSLIDE].stuff)->length=500;
  471.     }
  472.     
  473.     if (tp&HSLIDE)
  474.     {
  475.         wind->widgets[XAW_HSLIDE].behaviour[XACB_DISPLAY]=&display_hslide;
  476.         wind->widgets[XAW_HSLIDE].behaviour[XACB_CLICK]=&drag_hslide;
  477.         wind->widgets[XAW_HSLIDE].behaviour[XACB_DCLICK]=NULL;
  478.         wind->widgets[XAW_HSLIDE].behaviour[XACB_DRAG]=&drag_hslide;
  479.         wind->widgets[XAW_HSLIDE].loc=stdl_hslide;
  480.         wind->widgets[XAW_HSLIDE].stat=XAW_PLAIN;
  481.         wind->widgets[XAW_HSLIDE].w=ICON_W;
  482.         wind->widgets[XAW_HSLIDE].h=ICON_H;
  483.         wind->widgets[XAW_HSLIDE].stuff=(void*)malloc(sizeof(XA_SLIDER_WIDGET));
  484.         ((XA_SLIDER_WIDGET*)wind->widgets[XAW_HSLIDE].stuff)->position=0;
  485.         ((XA_SLIDER_WIDGET*)wind->widgets[XAW_HSLIDE].stuff)->length=500;
  486.     }
  487.  
  488.     if (tp&INFO)
  489.     {
  490.         wind->widgets[XAW_INFO].behaviour[XACB_DISPLAY]=&display_info;
  491.         wind->widgets[XAW_INFO].behaviour[XACB_CLICK]=NULL;
  492.         wind->widgets[XAW_INFO].behaviour[XACB_DCLICK]=NULL;
  493.         wind->widgets[XAW_INFO].behaviour[XACB_DRAG]=NULL;
  494.         wind->widgets[XAW_INFO].loc=stdl_info;
  495.         wind->widgets[XAW_INFO].stat=XAW_PLAIN;
  496.         wind->widgets[XAW_INFO].w=top_w;
  497.         wind->widgets[XAW_INFO].h=display.c_max_h;
  498.         wind->widgets[XAW_INFO].stuff=(void*)"Info Bar";        /* Give the window a default info line until the client changes it */
  499.         
  500.         if (tp&(NAME|CLOSE|FULLER))
  501.         {
  502.             if (display.c_max_h+6>ICON_H+2)
  503.                 wind->widgets[XAW_INFO].loc.y+=display.c_max_h+1;
  504.             else
  505.                 wind->widgets[XAW_INFO].loc.y+=ICON_H+1;
  506.         }
  507.         
  508.         bit_mask=tp&(~(INFO|NAME|CLOSE|FULLER));
  509.         for (wd=0; wd<XA_MAX_WIDGETS; wd++)    /* Shift any widgets we might interfere with */
  510.         {
  511.             if (bit_mask&1L)
  512.             {
  513.                 if (((wind->widgets[wd].loc.relative_type==LT)
  514.                     ||(wind->widgets[wd].loc.relative_type==RT))
  515.                     ||(wind->widgets[wd].loc.relative_type==CT))
  516.                 {
  517.                     wind->widgets[wd].loc.y+=wind->widgets[XAW_INFO].h+2;
  518.                 }
  519.             }
  520.             bit_mask=bit_mask>>1;
  521.         }
  522.     }
  523.  
  524. /* do this last as it's a variable size depending on which widgets are on the top bar */
  525.     if (tp&NAME)
  526.     {
  527.         wind->widgets[XAW_TITLE].behaviour[XACB_DISPLAY]=&display_title;
  528.         wind->widgets[XAW_TITLE].behaviour[XACB_CLICK]=&click_title;
  529.         wind->widgets[XAW_TITLE].behaviour[XACB_DCLICK]=&dclick_title;
  530.         wind->widgets[XAW_TITLE].behaviour[XACB_DRAG]=&drag_title;
  531.         wind->widgets[XAW_TITLE].loc=stdl_title;
  532.         wind->widgets[XAW_TITLE].stat=XAW_PLAIN;
  533.         wind->widgets[XAW_TITLE].w=top_w;                        /* Actually, this is re-calculated anyway... */
  534.         wind->widgets[XAW_TITLE].h=display.c_max_h;
  535.         wind->widgets[XAW_TITLE].stuff=(void*)"XaAES Window";    /* Give the window a default title until the client changes it */
  536.         
  537.         bit_mask=tp&(~(INFO|NAME|CLOSE|FULLER));
  538.         for (wd=0; wd<XA_MAX_WIDGETS; wd++)    /* Shift any widgets we might interfere with */
  539.         {
  540.             if (bit_mask&1L)
  541.             {
  542.                 if (((wind->widgets[wd].loc.relative_type==LT)
  543.                     ||(wind->widgets[wd].loc.relative_type==RT))
  544.                     ||(wind->widgets[wd].loc.relative_type==CT))
  545.                 {
  546.                     wind->widgets[wd].loc.y+=wind->widgets[XAW_TITLE].h;
  547.                 }
  548.             }
  549.             bit_mask=bit_mask>>1;
  550.         }
  551.     }
  552.     
  553. }
  554.  
  555. /*
  556.     Attach a menu to a window....probably let this be access via wind_set one day
  557. */
  558. void set_menu_widget(XA_WINDOW *wind, XA_WIDGET_LOCATION loc, OBJECT *obj)
  559. {
  560.     XA_WIDGET_TREE *nt=(XA_WIDGET_TREE*)malloc(sizeof(XA_WIDGET_TREE));
  561.  
  562.     if (!nt)
  563.         return;
  564.  
  565.     DIAGS(("set_menu_widget(wind=%d,obj=%lx):new@%lx\n",wind->handle,obj,nt));
  566.  
  567. #if GENERATE_DIAGS
  568.     if (!nt)
  569.     {
  570.         DIAGS((" - unable to allocate widget.\n"));
  571.     }
  572. #endif
  573.  
  574.     nt->tree=obj;
  575.     
  576.     wind->widgets[XAW_MENU].behaviour[XACB_DISPLAY]=&display_menu_widget;
  577.     wind->widgets[XAW_MENU].behaviour[XACB_CLICK]=&click_menu_widget;
  578.     wind->widgets[XAW_MENU].behaviour[XACB_DCLICK]=NULL;
  579.     wind->widgets[XAW_MENU].behaviour[XACB_DRAG]=&click_menu_widget;
  580.     wind->widgets[XAW_MENU].loc=loc;
  581.     wind->widgets[XAW_MENU].stat=XAW_PLAIN;
  582.     wind->widgets[XAW_MENU].w=wind->w-4;
  583.     wind->widgets[XAW_MENU].h=display.c_max_h;
  584.     wind->widgets[XAW_MENU].stuff=(void*)nt;
  585.  
  586.     calc_work_area(wind);            /* Recalculate the work area to include the new menu widget */
  587. }
  588.  
  589. /*
  590.     Attach a toolbar to a window....probably let this be access via wind_set one day
  591. */
  592. void set_toolbar_widget(XA_WINDOW *wind, XA_WIDGET_LOCATION loc, OBJECT *form)
  593. {
  594.     XA_WIDGET_TREE *nt=(XA_WIDGET_TREE*)malloc(sizeof(XA_WIDGET_TREE));
  595.     short f;
  596.     short startedit=0;
  597.  
  598. #if GENERATE_DIAGS
  599.     if (!nt)
  600.     {
  601.         DIAGS(("set_toolbar_widget - unable to allocate widget.\n"));
  602.     }
  603. #endif
  604.  
  605.     nt->tree=form;
  606.     nt->handler=NULL;    /* by default there is no handler for confirmed selections */
  607.     nt->owner = AESpid;
  608.  
  609.     f=0;
  610.     do {
  611.         if (form[f].ob_flags & EDITABLE)
  612.         {
  613.             startedit = f;
  614.             break;
  615.         }
  616.         f++;
  617.     } while (!(form[f].ob_flags & LASTOB));
  618.     
  619.     nt->edit_obj = startedit;
  620.     nt->edit_pos = 0;
  621.     
  622.     if (startedit)         /* Set up keypress handler if needed */
  623.     {
  624.         TEDINFO *te = (TEDINFO*)form[startedit].ob_spec;
  625.  
  626.         do {                                    /* Ensure that there aren't two fields flagged as the */
  627.             form[f].ob_state &= ~IS_EDIT;        /* current edit field */
  628.             f++;
  629.         } while(!(form[f].ob_flags & LASTOB));
  630.         
  631.         wind->keypress = &handle_form_key;
  632.         form[startedit].ob_state |= IS_EDIT;
  633.         te->te_tmplen = strlen(te->te_ptext);
  634.         nt->edit_pos = te->te_tmplen;
  635.     }
  636.     
  637.     wind->widgets[XAW_TOOLBAR].behaviour[XACB_DISPLAY]=&display_object_widget;
  638.     wind->widgets[XAW_TOOLBAR].behaviour[XACB_CLICK]=&click_object_widget;
  639.     wind->widgets[XAW_TOOLBAR].behaviour[XACB_DCLICK]=&dclick_object_widget;
  640.     wind->widgets[XAW_TOOLBAR].behaviour[XACB_DRAG]=&click_object_widget;
  641.     wind->widgets[XAW_TOOLBAR].loc=loc;
  642.     wind->widgets[XAW_TOOLBAR].stat=XAW_TOOLBARSTATE;    /* Special status value for toolbars */
  643.     wind->widgets[XAW_TOOLBAR].w=form->ob_width;
  644.     wind->widgets[XAW_TOOLBAR].h=form->ob_height;
  645.     wind->widgets[XAW_TOOLBAR].stuff=(void*)nt;
  646.  
  647.     calc_work_area(wind);            /* Recalculate the work area to include the new menu widget */
  648. }
  649.  
  650. /* Process widget clicks, and call the appropriate handler routines */
  651. /* This is the main routine for handling window interaction from a users perspective. */
  652. /* Each widget has a set of behaviours (display, drag, click, etc) for each of it's widgets. */
  653. /* - these can be changed on an individual basis, so the close widget of one window might */
  654. /*   call a that sends a 'go back up a directory' message to the desktop, where-as on another */
  655. /*   it may just take the GEM default and send a WM_CLOSED message to the application. */
  656. /* NOTE: If a widget has no XACB_DISPLAY behaviour, it will not recieve clicks (this is */
  657. /* deliberate as it's not a good idea to have invisible widgets that still get clicked */
  658. /* on. */
  659. short do_widgets(XA_WINDOW *w, MOOSE_BUTTON_DATA *md)
  660. {
  661.     XA_RECT_LIST *rl=rect_get_system_first(w);
  662.     XA_WIDGET *widg, *this_widget=NULL;
  663.     WidgetCallback wc,disp,wdrag;
  664.     short f, clicks, rtn=TRUE;
  665.     short x,y,rx,ry,b;
  666.     
  667.     clicks=md->clicks;
  668.     if (clicks>2) clicks=2;
  669.  
  670.     for(f=0; (f<XA_MAX_WIDGETS)&&(this_widget==NULL); f++)        /* Scan through widgets to find the one we clicked on */
  671.     {
  672.         widg=w->widgets+f;
  673.         disp=widg->behaviour[XACB_DISPLAY];        /* get the redraw function for this widget */
  674.         if (disp)
  675.         {
  676.             rp_2_ap(w, widg, &x, &y);    /* Convert relative coords and window location to absolute screen location */
  677.  
  678.             if ((((md->x>x)&&(md->y>y))&&(md->x<x+widg->w))&&(md->y<y+widg->h))
  679.             {
  680.                 this_widget=widg;            /* Found a widget - this_widget acts as a flag that says to absorb the click */
  681.  
  682.                 widg->click_x=md->x-x;     /* Mark where the click occurred (relative to the widget) */
  683.                 widg->click_y=md->y-y;    
  684.  
  685.                                             /* We don't auto select & pre-display for a menu or toolbar widget */
  686.                 if ((f!=XAW_MENU)&&(f!=XAW_TOOLBAR))
  687.                 {
  688.                     widg->stat=XAW_SELECTED;    /* Flag the widget as selected */
  689.                 
  690.                     v_hide_c(V_handle);
  691.                     for(rl=rect_get_system_first(w); rl; rl=rect_get_system_next(w))                /* Walk the rectangle list */
  692.                     {
  693.                         set_clip(rl->x, rl->y, rl->w, rl->h);
  694.                         (*disp)(w, this_widget);    /* display the selected widget */
  695.                     }
  696.                     v_show_c(V_handle, 1);
  697.                 }
  698.  
  699.                 wdrag=this_widget->behaviour[XACB_DRAG];    /* get the click-drag function for this widget */
  700.  
  701.                 vq_mouse(V_handle, &b,&rx,&ry);
  702.                 if ((b)&&(wdrag))    /* If the mouse button is still down do a drag (if the widget has a drag behaviour) */
  703.                 {
  704.                     rtn=(*wdrag)(w, this_widget);
  705.                 }else{                            /* otherwise, process as a mouse click(s) */
  706.     
  707.                     while (b)                    /* wait for the mouse to be released */
  708.                         vq_mouse(V_handle, &b,&rx,&ry);
  709.                 
  710.                     if ((((rx>x)&&(ry>y))&&(rx<x+widg->w))&&(ry<y+widg->h))
  711.                     {
  712.                         wc=this_widget->behaviour[clicks];
  713.                         if (wc)                            /* If the widget has a click behaviour, call it */
  714.                         {
  715.                             rtn=(*wc)(w, this_widget);
  716.                         }
  717.                     }
  718.                 }
  719.                 
  720.                 if (rtn)    /* If the widget click/drag function returned TRUE we reset the state of the widget */
  721.                 {
  722.                     widg->stat=XAW_PLAIN;            /* Flag the widget as de-selected */
  723.             
  724.                     v_hide_c(V_handle);
  725.                     for(rl=rect_get_system_first(w); rl; rl=rect_get_system_next(w))    /* Walk the rectangle list */
  726.                     {
  727.                         set_clip(rl->x, rl->y, rl->w, rl->h);
  728.                         (*disp)(w, this_widget);    /* display the selected widget */
  729.                     }
  730.                     v_show_c(V_handle, 1);
  731.                 }
  732.             }
  733.         }
  734.     }
  735.  
  736.     if (this_widget) return TRUE;    /* Button click was used up by the GUI */
  737.     
  738.     return FALSE;                    /* Button click can be passed on to applications as we didn't use it for a widget */
  739. }
  740.